package com.springboot.cloud.demos.ribbon.service;

import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.wxpay.sdk.WXPay;
import com.github.wxpay.sdk.WXPayUtil;
import com.springboot.cloud.common.core.entity.vo.Result;
import com.springboot.cloud.common.core.exception.SystemErrorType;
import com.springboot.cloud.common.core.util.DateUtils;
import com.springboot.cloud.common.web.entity.constant.WeixinConstant;
import com.springboot.cloud.common.web.redis.ExpireTimeConstant;
import com.springboot.cloud.demos.entity.enums.CancelType;
import com.springboot.cloud.demos.entity.enums.OrderStatus;
import com.springboot.cloud.demos.entity.enums.PayType;
import com.springboot.cloud.demos.entity.form.OrderForm;
import com.springboot.cloud.demos.entity.form.OrderQueryForm;
import com.springboot.cloud.demos.entity.param.OrderQueryParam;
import com.springboot.cloud.demos.entity.po.Order;
import com.springboot.cloud.demos.ribbon.config.WeixinPayConfig;
import com.springboot.cloud.demos.ribbon.weixin.WeixinPayUtil;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.client.RestTemplate;

import java.math.BigDecimal;
import java.util.*;

@Service
public class OrderService {

    @Autowired
    RestTemplate restTemplate;
    @Autowired
    private WeixinPayUtil weixinPayUtil;
    @SentinelResource(fallback = "conditionsFallback")
    public Result conditions(@RequestBody OrderQueryParam param) {

        Result result = restTemplate.postForEntity("http://producer/order/conditions", param, Result.class).getBody();

        if (result.isSuccess()) {
            List<Map<String, Object>> newList = new ArrayList<>();
            List<Map<String, Object>> list = (List<Map<String, Object>>) result.getData();
            for (Map<String, Object> map : list) {
                Map order = setExpireSecond(map);
                newList.add(order);
            }
            return Result.success(newList);
        }
        return result;
    }

    private Map<String, Object> setExpireSecond(Map<String, Object> order) {
        // 当订单为未付款时，计算订单的过期时间
        if (order.get("status").toString().equals(OrderStatus.unPay.getCode())) {
            Date createdTime = DateUtils.stringToDate(order.get("createdTime").toString());
            Date expireTime = this.getExpireTime(createdTime);
            Date currentTime = new Date();
            long expiredSecond = expireTime.getTime() - currentTime.getTime();
            order.put("expiredSecond", expiredSecond / 1000);

            // 如果已经过期且订单状态不是取消状态, 那么设置订单为取消状态
            if (expiredSecond <= 0 && !order.get("status").toString().equals(OrderStatus.cancel.getCode())) {
                OrderForm orderForm = new OrderForm();
                orderForm.setStatus(OrderStatus.cancel.getCode());
                orderForm.setCancelType(CancelType.outTimeCancel.getCode());
                orderForm.setCancelTime(new Date());
                orderForm.setId(order.get("id").toString());
                update(orderForm);
                order.put("status", OrderStatus.cancel.getCode());
            }

        }

        return order;

    }

    /**
     * 获取过期时间
     *
     * @param createTime
     * @return
     */
    private Date getExpireTime(Date createTime) {
        int expiredSecond = Math.toIntExact(ExpireTimeConstant.HALF_AN_HOUR); // 订单超时时间定义为30分钟
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(createTime);
        calendar.add(Calendar.SECOND, +expiredSecond);
        Date expiredTime = calendar.getTime();

        return expiredTime;
    }

    public Result conditionsFallback(@RequestBody Map params) {
        return Result.fail(SystemErrorType.SYSTEM_BUSY);
    }

    @SentinelResource(fallback = "orderFallback")
    public Result<Order> order(String orderId) {
        return restTemplate.getForEntity("http://producer/order/{orderId}", Result.class, orderId).getBody();
    }

    public Result orderFallback(@RequestBody Map params) {
        return Result.fail(SystemErrorType.SYSTEM_BUSY);
    }

    @SentinelResource(fallback = "saveFallback")
    public Result<Order> save(@RequestBody OrderForm orderForm) {
        Result result = Result.fail();
        Result levelResult = restTemplate.getForEntity("http://producer/memberCard/{id}", Result.class, orderForm.getMemberCardId()).getBody();
        if (levelResult.isSuccess()) {
            orderForm.setPrice(new BigDecimal(((LinkedHashMap) levelResult.getData()).get("price").toString()));
            orderForm.setOriginalPrice(new BigDecimal(((LinkedHashMap) levelResult.getData()).get("price").toString()));
            orderForm.setPayMoney(new BigDecimal(((LinkedHashMap) levelResult.getData()).get("price").toString()));
            result = restTemplate.postForEntity("http://producer/order", orderForm, Result.class).getBody();
        }
        return result;
    }

    @SentinelResource(fallback = "updateFallback")
    public Result update(@RequestBody OrderForm orderForm) {
        restTemplate.put("http://producer/order/{1}", orderForm, orderForm.getId());
        return Result.success();
    }

    @SentinelResource(fallback = "conditionsFallback")
    public Result<Page> page(@RequestBody OrderQueryForm param) {
        return restTemplate.postForEntity("http://producer/order/page", param, Result.class).getBody();
    }

    public Result saveFallback(@RequestBody OrderForm orderForm) {
        return Result.fail(SystemErrorType.SYSTEM_BUSY);
    }

    public Result updateFallback(Order order) {
        return Result.fail(SystemErrorType.SYSTEM_BUSY);
    }

    public void delete(String orderId) {
        restTemplate.delete("http://producer/order/{orderId}", orderId);
    }

}
